package edg.db;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Statement;
import java.text.SimpleDateFormat;

import edg.acm.ConfigurationModel;
import edg.acm.Files;

public class Simulator {
	
	private static final SimpleDateFormat DATETIME =
		new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	/**
	 * This method should only be called if a simulation will be started with
	 * this cm (no partial saves).
	 * @param cm ConfigurationModel object to saved.
	 * @return ID assigned to this configuration model.
	 */
	public static int save(ConfigurationModel cm) {
		
		int doctor = (Integer)cm.getValue("doctor");
		int nurse = (Integer)cm.getValue("nurse");
		int externalTriage = (Integer)cm.getValue("external triage");
		int internalTriage = (Integer)cm.getValue("internal triage");
		int externalClerk = (Integer)cm.getValue("external clerk");
		int internalClerk = (Integer)cm.getValue("internal clerk");
		int bed = (Integer)cm.getValue("bed");
		int labTech = (Integer)cm.getValue("lab tech");
		int ctscanTech = (Integer)cm.getValue("ctscan tech");
		int xrayTech = (Integer)cm.getValue("xray tech");
		int ultrasoundTech = (Integer)cm.getValue("ultrasound tech");
		int rate = (Integer)cm.getValue("rate");
		int runs = (Integer)cm.getValue("runs");
		int hours = (Integer)cm.getValue("hours");
		int acuity1 = (Integer)cm.getValue("acuity1");
		int acuity2 = (Integer)cm.getValue("acuity2");
		int acuity3 = (Integer)cm.getValue("acuity3");
		int acuity4 = (Integer)cm.getValue("acuity4");
		int acuity5 = (Integer)cm.getValue("acuity5");
		int acuity6 = (Integer)cm.getValue("acuity6");
		int walkin = (Integer)cm.getValue("walkin");
				
		Statement statement = Database.query(
				
				"INSERT " +
				"INTO cms (" +
					"doctor, " +
					"nurse, " +
					"external_triage, " +
					"internal_triage, " +
					"external_clerk, " +
					"internal_clerk, " +
					"bed, " +
					"lab_tech, " +
					"ctscan_tech, " +
					"xray_tech, " +
					"ultrasound_tech, " +
					"rate, " +
					"runs, " +
					"hours, " +
					"acuity1, " +
					"acuity2, " +
					"acuity3, " +
					"acuity4, " +
					"acuity5, " +
					"acuity6, " +
					"walkin" +
				") " +
				"VALUES(" +
					doctor + ", " +
					nurse + ", " +
					externalTriage + ", " +
					internalTriage + ", " +
					externalClerk + ", " +
					internalClerk + ", " +
					bed + ", " +
					labTech + ", " +
					ctscanTech + ", " +
					xrayTech + ", " +
					ultrasoundTech + ", " +
					rate + ", " +
					runs + ", " +
					hours + ", " +
					acuity1 + ", " +
					acuity2 + ", " +
					acuity3 + ", " +
					acuity4 + ", " +
					acuity5 + ", " +
					acuity6 + ", " +
					walkin +
				");"
					
			);
		
		if(statement == null) {
			return -1;
		}
		
		// This is a hack to get the last inserted id.  It has potential
		// concurrency issues.
		statement = Database.query(
				
				"SELECT MAX(id) AS last_id " +
				"FROM cms;"
				
			);
		
		try {
			statement.getResultSet().first();
			return statement.getResultSet().getInt("last_id");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return -1;
	}
	
	/**
	 * Start JSim.
	 * @param files Output allocation and resource utilization file locations.
	 * @param cm Configuration model used to run simulation.
	 * @return ID assigned to the run.
	 */
	public static int start(Files files, ConfigurationModel cm) {
		
		Database.query(
				
				"INSERT INTO runs (user_id, cm_id, started, name) " +
				"VALUES(" +
					cm.getUser() + ", " +
					cm.getID() + ", " +
					"'" + DATETIME.format(System.currentTimeMillis()) + "', " +
					"'" + DATETIME.format(System.currentTimeMillis()) + "'" +
				")"
				
			);
		
		// This is a hack to get the last inserted id.  It has potential
		// concurrency issues.
		Statement statement = Database.query(
				
				"SELECT MAX(id) AS last_id " +
				"FROM runs;"
				
			);
		
		int runId = -1;
		try {
			statement.getResultSet().first();
			runId = statement.getResultSet().getInt("last_id");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		try {
			System.out.println("Entering java command");
			ProcessBuilder pb = new ProcessBuilder();
			pb.command("java", "-Xmx256M",
					"-cp", System.getProperty("cs320.company1.jsim_jar", "jsim.jar"),
					"-Dinstall.dir=.",
					"-Dlaser.romeo.config="+files.romeo,
					"laser.juliette.driver.Driver",
					System.getProperty("cs320.company1.jul_file", "EDCare.jul"),
					files.jsim);
			pb.redirectErrorStream();
			
			//java -Xmx256M -cp jsim.jar -Dinstall.dir=. -Dlaser.romeo.config=Users/mharrison/Dev/cs320/edgdevelopment/jsim/romeo-config29732.xml laser.juliette.driver.Driver EDCare.jul /Users/mharrison/Dev/cs320/edgdevelopment/jsim/config29728.jsim
			System.out.println(pb.command());
			System.out.println(pb.environment());
			System.out.println(pb.directory());
			System.out.println(files.romeo);
			Process proc = pb.start();
			System.out.println("Beginning read of simulation.");
			InputStream inputstream = proc.getInputStream();
			InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
			BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
			
			String line;
			while((line = bufferedreader.readLine()) != null) {
				System.out.println(line);
			}
			
			// Wait for JSim to finish
			proc.waitFor();
			System.out.println("Procwait");
			Parser.parseAllocation(files.allocation, runId);
			Parser.parseResUtilization(files.utilization, runId);
			System.out.println("Starting startcalc with runID" + runId);
			StatCalculator.Calculate(runId);
			System.out.println("Ending");
		} catch (Exception ex) {
			System.out.println("Oh snap");
			ex.printStackTrace();
			return -1;
			
		}
		return runId;
	}
	
}

